home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr47
/
335_04.zip
/
FRAOSUB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-13
|
15KB
|
793 lines
/*
HEADER: ;
TITLE: Frankenstein Cross Assemblers;
VERSION: 2.0;
DESCRIPTION: " Reconfigurable Cross-assembler producing Intel (TM)
Hex format object records. ";
SYSTEM: UNIX, MS-Dos ;
FILENAME: fraosub.c;
WARNINGS: "This software is in the public domain.
Any prior copyright claims are relinquished.
This software is distributed with no warranty whatever.
The author takes no responsibility for the consequences
of its use." ;
SEE-ALSO: frasmain.c;
AUTHORS: Mark Zenier;
*/
/*
description output pass utility routines
history September 27, 1987
March 15, 1988 release 1.1 WIDTH
September 14, 1990 Dosify, 6 char unique names
*/
#include <stdio.h>
#include "frasmdat.h"
#include "fragcon.h"
#define OUTRESULTLEN 256
#define NUMHEXPERL 16
#define SOURCEOFFSET 24
#define NUMHEXSOURCE 6
int linenumber = 0;
char lineLbuff[INBUFFSZ];
int lineLflag = FALSE;
static unsigned char outresult[OUTRESULTLEN];
static int nextresult;
static long genlocctr, resultloc;
static char *oeptr;
#define MAXIMPWID 24
static long widthmask[MAXIMPWID+1] =
{
/* 0 */ 1L,
/* 1 */ 1L,
/* 2 */ (1L << 2 ) -1,
/* 3 */ (1L << 3 ) -1,
/* 4 */ (1L << 4 ) -1,
/* 5 */ (1L << 5 ) -1,
/* 6 */ (1L << 6 ) -1,
/* 7 */ (1L << 7 ) -1,
/* 8 */ (1L << 8 ) -1,
/* 9 */ (1L << 9 ) -1,
/* 10 */ (1L << 10 ) -1,
/* 11 */ (1L << 11 ) -1,
/* 12 */ (1L << 12 ) -1,
/* 13 */ (1L << 13 ) -1,
/* 14 */ (1L << 14 ) -1,
/* 15 */ (1L << 15 ) -1,
/* 16 */ (1L << 16 ) -1,
/* 17 */ (1L << 17 ) -1,
/* 18 */ (1L << 18 ) -1,
/* 19 */ (1L << 19 ) -1,
/* 20 */ (1L << 20 ) -1,
/* 21 */ (1L << 21 ) -1,
/* 22 */ (1L << 22 ) -1,
/* 23 */ (1L << 23 ) -1,
/* 24 */ (1L << 24 ) -1
};
static long dgethex()
/*
description convert the character string pointed to by
the output expression pointer to a long integer
globals oeptr, the output expression pointer
return the value
*/
{
long rv = 0;
while( *oeptr != '\0')
{
switch(*oeptr)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
rv = (rv << 4) + ((*oeptr) - '0');
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
rv = (rv << 4) + ((*oeptr) - 'a' + 10);
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
rv = (rv << 4) + ((*oeptr) - 'A' + 10);
break;
default:
return rv;
}
oeptr++;
}
return rv;
}
outphase()
/*
description process all the lines in the intermediate file
globals the input line
the output expression pointer
line number
file name
the binary output array and counts
*/
{
int firstchar;
for(;;)
{
if((firstchar = fgetc(intermedf)) == EOF)
break;
if(firstchar == 'L')
{
if(listflag)
flushlisthex();
if( fgets(&lineLbuff[1], INBUFFSZ-1, intermedf)
== (char *)NULL)
{
frp2error( "error or premature end of intermediate file");
break;
}
lineLflag = TRUE;
}
else
{
finbuff[0] = firstchar;
if(fgets( &finbuff[1], INBUFFSZ-1, intermedf)
== (char *)NULL)
{
frp2error("error or premature end of intermediate file");
break;
}
}
switch(firstchar)
{
case 'E': /* error */
if(listflag)
{
flushsourceline();
fputs(&finbuff[2], loutf);
}
else
{
fprintf(loutf, "%s - line %d - %s",
currentfnm, linenumber, &finbuff[2]);
}
break;
case 'L': /* listing */
linenumber++;
break;
case 'C': /* comment / uncounted listing */
if(listflag)
{
char *stuff = strchr(finbuff, '\n');
if(stuff != NULL)
*stuff = '\0';
fprintf(loutf,"%-*.*s",
SOURCEOFFSET, SOURCEOFFSET, &finbuff[2]);
if(lineLflag)
{
fputs(&lineLbuff[2], loutf);
lineLflag = FALSE;
}
else
{
fputc('\n', loutf);
}
}
break;
case 'P': /* location set */
oeptr = &finbuff[2];
currseg = dgethex();
oeptr++;
genlocctr = locctr = dgethex();
break;
case 'D': /* data */
oeptr = &finbuff[2];
nextresult = 0;
resultloc = genlocctr;
outeval();
if(hexflag)
outhexblock();
if(listflag)
listhex();
break;
case 'F': /* file start */
{
char *tp;
if( (tp = strchr(finbuff,'\n')) != (char *)NULL)
*tp = '\0';
strncpy(currentfnm, &finbuff[2], 100);
currentfnm[99] = '\0';
}
lnumstk[currfstk++] = linenumber;
linenumber = 0;
break;
case 'X': /* file resume */
{
char *tp;
if( (tp = strchr(finbuff,'\n')) != (char *)NULL)
*tp = '\0';
strncpy(currentfnm, &finbuff[2], 100);
currentfnm[99] = '\0';
}
linenumber = lnumstk[--currfstk];
break;
default:
frp2error("unknown intermediate file command");
break;
}
}
if(hexflag)
flushhex();
if(listflag)
flushlisthex();
}
outeval()
/*
description convert the polish form character string in the
intermediate file 'D' line to binary values in the
output result array.
globals the output expression pointer
the output result array
*/
{
register long etop = 0;
register struct evstkel *estkm1p = &estk[0];
while( *oeptr != '\0')
{
switch(*oeptr)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
etop = (etop << 4) + ((*oeptr) - '0');
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
etop = (etop << 4) + ((*oeptr) - 'a' + 10);
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
etop = (etop << 4) + ((*oeptr) - 'A' + 10);
break;
#include "fraeuni.h"
#include "fraebin.h"
case IFC_SYMB:
{
struct symel *tsy;
tsy = symbindex[etop];
if(tsy -> seg <= 0)
{
frp2undef(tsy);
etop = 0;
}
else
{
if(tsy -> seg == SSG_EQU ||
tsy -> seg == SSG_SET)
{
frp2warn( "forward reference to SET/EQU symbol");
}
etop = tsy -> value;
}
}
break;
case IFC_CURRLOC:
etop = genlocctr;
break;
case IFC_PROGCTR:
etop = locctr;
break;
case IFC_DUP:
if(estkm1p >= &estk[PESTKDEPTH-1])
{
frp2error("expression stack overflow");
}
else
{
(++estkm1p)->v = etop;
}
break;
case IFC_LOAD:
if(estkm1p >= &estk[PESTKDEPTH-1])
{
frp2error("expression stack overflow");
}
else
{
(++estkm1p)->v = etop;
}
etop = 0;
break;
case IFC_CLR:
etop = 0;
break;
case IFC_CLRALL:
etop = 0;
estkm1p = &estk[0];
break;
case IFC_POP:
etop = (estkm1p--)->v;
break;
case IFC_TESTERR:
if(etop)
{
frp2error(
"expression fails validity test");
}
break;
case IFC_SWIDTH:
if( etop > 0 && etop <= MAXIMPWID)
{
if( estkm1p->v < -(widthmask[etop-1]+1) ||
estkm1p->v > widthmask[etop-1] )
{
frp2error(
"expression exceeds available field width");
}
etop = ((estkm1p--)->v) & widthmask[etop];
}
else
frp2error("unimplemented width");
break;
case IFC_WIDTH:
if( etop > 0 && etop <= MAXIMPWID)
{
if( estkm1p->v < -(widthmask[etop-1]+1) ||
estkm1p->v > widthmask[etop] )
{
frp2error(
"expression exceeds available field width");
}
etop = ((estkm1p--)->v) & widthmask[etop];
}
else
frp2error("unimplemented width");
break;
case IFC_IWIDTH:
if( etop > 0 && etop <= MAXIMPWID)
{
if( estkm1p->v < 0 ||
estkm1p->v > widthmask[etop] )
{
frp2error(
"expression exceeds available field width");
}
etop = ((estkm1p--)->v) & widthmask[etop];
}
else
frp2error("unimplemented width");
break;
case IFC_EMU8:
if( etop >= -128 && etop <= 255)
{
outresult[nextresult++] = etop & 0xff;
}
else
{
outresult[nextresult++] = 0;
frp2error(
"expression exceeds available field width");
}
genlocctr ++;
etop = 0;
break;
case IFC_EMS7:
if(etop >= -128 && etop <= 127)
{
outresult[nextresult++] = etop & 0xff;
}
else
{
outresult[nextresult++] = 0;
frp2error(
"expression exceeds available field width");
}
genlocctr ++;
etop = 0;
break;
case IFC_EM16:
if(etop >= -32768L && etop <= 65535L)
{
outresult[nextresult++] = (etop >> 8) & 0xff;
outresult[nextresult++] = etop & 0xff;
}
else
{
outresult[nextresult++] = 0;
outresult[nextresult++] = 0;
frp2error(
"expression exceeds available field width");
}
genlocctr += 2;
etop = 0;
break;
case IFC_EMBR16:
if(etop >= -32768L && etop <= 65535L)
{
outresult[nextresult++] = etop & 0xff;
outresult[nextresult++] = (etop >> 8) & 0xff;
}
else
{
outresult[nextresult++] = 0;
outresult[nextresult++] = 0;
frp2error(
"expression exceeds available field width");
}
genlocctr += 2;
etop = 0;
break;
default:
break;
}
oeptr++;
}
}
static long lhaddr, lhnextaddr;
static int lhnew, lhnext = 0;
static unsigned char listbuffhex[NUMHEXPERL];
flushlisthex()
/*
description output the residue of the hexidecimal values for
the previous assembler statement.
globals the new hex list flag
*/
{
listouthex();
lhnew = TRUE;
}
listhex()
/*
description buffer the output result to block the hexidecimal
listing on the output file to NUMHEXPERL bytes per
listing line.
globals The output result array and count
the hex line buffer and counts
*/
{
register int cht;
register long inhaddr = resultloc;
if(lhnew)
{
lhaddr = lhnextaddr = resultloc;
lhnew = FALSE;
}
for(cht = 0; cht < nextresult; cht++)
{
if(lhnextaddr != inhaddr
|| lhnext >= (lineLflag ? NUMHEXSOURCE : NUMHEXPERL ) )
{
listouthex();
lhaddr = lhnextaddr = inhaddr;
}
listbuffhex[lhnext++] = outresult[cht];
lhnextaddr ++;
inhaddr ++;
}
}
listouthex()
/*
description print a line of hexidecimal on the listing
globals the hex listing buffer
*/
{
register int cn;
register int tc;
if(lhnext > 0)
{
fputc(hexch((int)lhaddr>>12), loutf);
fputc(hexch((int)lhaddr>>8), loutf);
fputc(hexch((int)lhaddr>>4), loutf);
fputc(hexch((int)lhaddr), loutf);
fputc(' ', loutf);
for(cn = 0; cn < lhnext; cn++)
{
fputc(hexch((int)(tc = listbuffhex[cn])>>4), loutf);
fputc(hexch(tc), loutf);
fputc(' ', loutf);
}
if( ! lineLflag)
fputc('\n', loutf);
}
if(lineLflag)
{
if(lineLbuff[2] != '\n')
{
switch(lhnext)
{
case 0:
fputs("\t\t\t",loutf);
break;
case 1:
case 2:
case 3:
fputs("\t\t",loutf);
break;
case 4:
case 5:
case 6:
fputs("\t",loutf);
default:
break;
}
fputs(&lineLbuff[2], loutf);
lineLflag = FALSE;
}
else
{
fputc('\n', loutf);
}
}
lhnext = 0;
}
#define INTELLEN 32
static long nextoutaddr, blockaddr;
static int hnextsub;
static char hlinebuff[INTELLEN];
outhexblock()
/*
description buffer the output result to group adjacent output
data into longer lines.
globals the output result array
the intel hex line buffer
*/
{
long inbuffaddr = resultloc;
static int first = TRUE;
int loopc;
if(first)
{
nextoutaddr = blockaddr = resultloc;
hnextsub = 0;
first = FALSE;
}
for(loopc = 0; loopc < nextresult; loopc++)
{
if(nextoutaddr != inbuffaddr || hnextsub >= INTELLEN)
{
intelout(0, blockaddr, hnextsub, hlinebuff);
blockaddr = nextoutaddr = inbuffaddr;
hnextsub = 0;
}
hlinebuff[hnextsub++] = outresult[loopc];
nextoutaddr++;
inbuffaddr++;
}
}
flushhex()
/*
description flush the intel hex line buffer at the end of
the second pass
globals the intel hex line buffer
*/
{
if(hnextsub > 0)
intelout(0, blockaddr, hnextsub, hlinebuff);
if(endsymbol != SYMNULL && endsymbol -> seg > 0)
intelout(1, endsymbol -> value, 0, "");
else
intelout(1, 0L, 0, "");
}
intelout(type, addr, count, data)
int type;
long addr;
int count;
char data[];
/*
description print a line of intel format hex data to the output
file
parameters see manual for record description
*/
{
register int temp, checksum;
fputc(':', hexoutf);
fputc(hexch(count>>4),hexoutf);
fputc(hexch(count),hexoutf);
fputc(hexch((int)addr>>12),hexoutf);
fputc(hexch((int)addr>>8),hexoutf);
fputc(hexch((int)addr>>4),hexoutf);
fputc(hexch((int)addr),hexoutf);
fputc(hexch(type>>4),hexoutf);
fputc(hexch(type),hexoutf);
checksum = ((addr >> 8) & 0xff) + (addr & 0xff) + (count & 0xff);
checksum += type & 0xff;
for(temp = 0; temp < count; temp ++)
{
checksum += data[temp] & 0xff;
fputc(hexch(data[temp] >> 4), hexoutf);
fputc(hexch(data[temp]), hexoutf);
}
checksum = (-checksum) & 0xff;
fputc(hexch(checksum>>4), hexoutf);
fputc(hexch(checksum), hexoutf);
fputc('\n',hexoutf);
}
frp2undef(symp)
struct symel * symp;
/*
description second pass - print undefined symbol error message on
the output listing device. If the the listing flag
is false, the output device is the standard output, and
the message format is different.
parameters a pointer to a symbol table element
globals the count of errors
*/
{
if(listflag)
{
flushsourceline();
fprintf(loutf," ERROR - undefined symbol %s\n", symp ->symstr);
}
else
fprintf(loutf, "%s - line %d - ERROR - undefined symbol %s\n",
currentfnm, linenumber, symp -> symstr);
errorcnt++;
}
frp2warn(str)
char * str;
/*
description second pass - print a warning message on the listing
file, varying the format for console messages.
parameters the message
globals the count of warnings
*/
{
if(listflag)
{
flushsourceline();
fprintf(loutf, " WARNING - %s\n", str);
}
else
fprintf(loutf, "%s - line %d - WARNING - %s\n",
currentfnm, linenumber, str);
warncnt++;
}
frp2error(str)
char * str;
/*
description second pass - print a message on the listing file
parameters message
globals count of errors
*/
{
if(listflag)
{
flushsourceline();
fprintf(loutf, " ERROR - %s\n", str);
}
else
fprintf(loutf, "%s - line %d - ERROR - %s\n",
currentfnm, linenumber, str);
errorcnt++;
}
flushsourceline()
/*
description flush listing line buffer before an error for
that line is printed
*/
{
if(listflag && lineLflag)
{
fputs("\t\t\t", loutf);
fputs(&lineLbuff[2], loutf);
lineLflag = FALSE;
}
}